package com.kandy.smart.trace.dubbo.filter;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.*;
import com.kandy.smart.trace.TraceContext;
import com.kandy.smart.trace.TraceThread;
import com.kandy.smart.trace.constant.TraceConstant;
import com.kandy.smart.trace.utils.IPUtil;
import com.kandy.smart.trace.utils.IdGenUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

import java.util.Arrays;
import java.util.UUID;

/**
 * Created by kandy on 18/8/14.
 */
@Activate(group = { Constants.CONSUMER },order = -10000)
public class TraceConsumerFilter implements Filter {
    private static Logger logger = LoggerFactory.getLogger(TraceConsumerFilter.class);

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        if(Boolean.TRUE.toString().equals(invocation.getAttachments().get(Constants.ASYNC_KEY))){
            RpcContext.getContext().getAttachments().remove(Constants.ASYNC_KEY);
        }

        // 获取上下文
        RpcContext rpcContext = RpcContext.getContext();
        TraceContext traceContext = TraceThread.getTraceThreadData(Thread.currentThread());

        if (null != traceContext && !StringUtils.isBlank(traceContext.getTraceId())){
            // 调用链,非根节点
            // 因consumer都是消费者,在消费者调用前必须调用interceptor或provider;若存在为空做新链处理
        }else {
            // 调用链,根节点(不存在,若出现做新链处理)
//            traceThreadData.setThreadId(UUID.randomUUID().toString().replaceAll("-","").toLowerCase());
            traceContext.setThreadId(String.valueOf(Thread.currentThread().getId()));
            traceContext.setTraceId(UUID.randomUUID().toString().replaceAll("-","").toLowerCase());
            traceContext.setParentId("root");
            traceContext.setAppId(IdGenUtil.getRandomGen6());
            traceContext.setLocalIp(IPUtil.getLocalHostIp());

            TraceThread.set(Thread.currentThread(),traceContext);
        }

        // rpcContext 赋值
        rpcContext.setAttachment(TraceConstant.TRACE_ID,traceContext.getTraceId());
        rpcContext.setAttachment(TraceConstant.PARENT_ID,traceContext.getAppId());
//        rpcContext.setAttachment(TraceConstant.CHILD_ID,UUID.randomUUID().toString().replaceAll("-","").toLowerCase());
        rpcContext.setAttachment(TraceConstant.CHILD_ID,IdGenUtil.getRandomGen6());
        rpcContext.setAttachment(TraceConstant.REMOTE_IP,traceContext.getLocalIp()); //本地IP为dubbo的远程IP

        // 设置MDC日志
        MDC.put("ThreadID",traceContext.getThreadId());
        MDC.put("TraceID",traceContext.getTraceId());
        MDC.put("ParentID",traceContext.getParentId());
        MDC.put("APPID",traceContext.getAppId());
        MDC.put("LocalIp",traceContext.getLocalIp());

//        traceThreadData.setThreadId(UUID.randomUUID().toString().replaceAll("-","").toLowerCase());
//        traceThreadData.setThreadId(String.valueOf(Thread.currentThread().getId()));
//        traceThreadData.setTraceId(rpcContext.getAttachment(TraceConstant.TRACE_ID));
//        traceThreadData.setParentId(rpcContext.getAttachment(TraceConstant.PARENT_ID));
//        traceThreadData.setAppId(rpcContext.getAttachment(TraceConstant.CHILD_ID));

        long start = System.currentTimeMillis();
        Result result = invoker.invoke(invocation);
        long elapsed = System.currentTimeMillis() - start;
        if (invoker.getUrl() != null) {
            logger.info("[{}], [{}], {}, [{}], [{}], [{}] ",invoker.getInterface(), invocation.getMethodName(), Arrays.toString(invocation.getArguments()), result.getValue(), result.getException(), elapsed);
        }
        return result;
    }
}
